package my.edu.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;

import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;

public class ChildrenLoader {

    /**
     * 从数据库查询子表并自动填充到父对象中
     *
     * @param parentList 父对象列表
     * @param parentIdGetter 获取父对象ID的方法
     * @param childQuery 执行子表查询的方法（接收父ID列表）
     * @param childParentIdGetter 获取子对象中的 parentId
     * @param childSetter 设置子对象列表到父对象中
     */
    public static <P, C, K> void loadAndFill(
            List<P> parentList,
            Function<P, K> parentIdGetter,
            Function<List<K>, List<C>> childQuery,
            Function<C, K> childParentIdGetter,
            BiConsumer<P, List<C>> childSetter
    ) {
        if (CollUtil.isEmpty(parentList)) return;

        // 1. 提取所有父ID
        List<K> parentIds = parentList.stream()
                .map(parentIdGetter)
                .distinct()
                .collect(Collectors.toList());

        // 2. 查询子表
        List<C> childList = childQuery.apply(parentIds);

        if (parentList == null || parentList.isEmpty()) return;

        // 1. 将子表按 parentId 分组
        Map<K, List<C>> childMap = Optional.ofNullable(childList)
                .orElse(Collections.emptyList())
                .stream()
                .collect(Collectors.groupingBy(childParentIdGetter));

        // 2. 将子表列表设置到对应父对象中
        for (P parent : parentList) {
            K parentId = parentIdGetter.apply(parent);
            List<C> children = childMap.getOrDefault(parentId, Collections.emptyList());
            childSetter.accept(parent, children);
        }
    }

    public static <P, C, K,T> void loadAndFillDTO(
            List<P> parentList,
            Function<P, K> parentIdGetter,
            Function<List<K>, List<C>> childQuery,
            Function<T, K> childParentIdGetter,
            Class<T> childDtoClass,
            BiConsumer<P, List<T>> childSetter
    ) {
        if (CollUtil.isEmpty(parentList)) return;

        // 1. 提取所有父ID
        List<K> parentIds = parentList.stream()
                .map(parentIdGetter)
                .distinct()
                .collect(Collectors.toList());

        // 2. 查询子表
        List<T> childList = BeanUtil.copyToList(childQuery.apply(parentIds), childDtoClass);

        if (parentList == null || parentList.isEmpty()) return;

        // 1. 将子表按 parentId 分组
        Map<K, List<T>> childMap = Optional.ofNullable(childList)
                .orElse(Collections.emptyList())
                .stream()
                .collect(Collectors.groupingBy(childParentIdGetter));

        // 2. 将子表列表设置到对应父对象中
        for (P parent : parentList) {
            K parentId = parentIdGetter.apply(parent);
            List<T> children = childMap.getOrDefault(parentId, Collections.emptyList());
            childSetter.accept(parent, children);
        }
    }
}